<template>
  <div class="banner" v-if="imglist" @mouseenter="mEnter" @mouseleave="mLeave">
    <ul
      class="content"
      :style="{
        transform: 'translateX(' + translateX + 'px)',
        transition: movingPageNum ? 'transform .3s' : 'unset',
      }"
      @transitionend="tranend"
      @mousedown="mDown"
      @touchstart="tStart"
      @touchmove="tMove"
      @touchend="tEnd"
      ref="content"
    >
      <li
        class="prev"
        v-for="count in pageNum"
        :key="count"
        :data-v="formatIdx(curIdx - (pageNum + 1 - count))"
      >
        <img :src="imglist[formatIdx(curIdx - (pageNum + 1 - count))]" />
      </li>
      <li class="cur" :data-v="formatIdx(curIdx)">
        <img :src="imglist[formatIdx(curIdx)]" />
      </li>
      <li
        class="next"
        v-for="count in pageNum"
        :key="count + pageNum"
        :data-v="formatIdx(curIdx + count)"
      >
        <img :src="imglist[formatIdx(curIdx + count)]" />
      </li>
    </ul>
    <div class="mark">
      <span
        v-for="(item, index) in imglist.length"
        :key="index"
        :class="{ active: index == curIdx }"
        :data-v="index"
        @click="change(index)"
      ></span>
    </div>
    <span @click="change(curIdx - 1)" class="button1"></span>
    <span @click="change(curIdx + 1)" class="button2"></span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      curIdx: 0,
      movingPageNum: 0,
      mousePos: {},
      translateX: 0,
      pageWidth: 0,
      imglist: null,
      timer: null,
    };
  },
  mounted() {
    this.$http
      .get("/banner")
      .then((d) => {
        this.imglist = d.data.banners.map((item) => item.imageUrl);
        this.$nextTick(() => {
          this.resetContent();
          this.restartAni();
        });
      }, 500)
      .catch((err) => {
        console.log(err);
      });
    window.onresize = () => {
      this.resetContent();
    };
  },
  destroyed() {
    window.onresize = null;
  },
  computed: {
    pageNum() {
      return this.imglist ? Math.max(0, this.imglist.length - 1) : 0;
    },
  },
  methods: {
    resetContent() {
      let content = this.$refs.content;
      if (!content) return;
      content.style.width = "100%";
      this.pageWidth = content.offsetWidth;
      content.style.width = this.pageWidth + "px";
      this.translateX = -this.pageWidth * this.pageNum;
      // 禁止拖拽页面图片
      content.ondragstart = function () {
        return false;
      };
    },
    mLeave() {
      !this.isDown && this.restartAni();
      this.isEnter = false;
    },
    mEnter() {
      clearTimeout(this.timer);
      this.isEnter = true;
    },
    mDown(e) {
      if (this.movingPageNum != 0) return;
      this.isDown = true;
      this.mousePos = {
        X: e.pageX,
        Y: e.pageY,
      };
      window.onmousemove = (e) => {
        this.translateX =
          -this.pageWidth * this.pageNum + e.pageX - this.mousePos.X;
        window.onmouseup = (e) => {
          if (this.movingPageNum != 0) return;
          this.isDown = false;
          let dtx = e.pageX - this.mousePos.X;
          let j = dtx < 0 ? -1 : 1;
          for (var i = this.pageNum; i >= 0; i--) {
            if (j * dtx > (i - 1) * this.pageWidth + 50) {
              this.movingPageNum = -j * i;
              if (this.translateX == (this.pageNum - j * i) * -this.pageWidth) {
                this.tranend();
              } else {
                this.translateX = (this.pageNum - j * i) * -this.pageWidth;
                if (this.movingPageNum == 0) this.tranend();
              }
              break;
            }
          }
          window.onmousemove = null;
          window.onmouseup = null;
        };
      };
    },
    tStart(e) {
      this.mEnter();
      if (e.cancelable) e.preventDefault();
      if (this.movingPageNum != 0) return;
      this.isDown = true;
      this.mousePos = {
        X: e.targetTouches[0].pageX,
        Y: e.targetTouches[0].pageY,
      };
    },
    tMove(e) {
      if (this.movingPageNum != 0) return;
      this.translateX =
        -this.pageWidth * this.pageNum +
        e.changedTouches[0].pageX -
        this.mousePos.X;
    },
    tEnd(e) {
      this.mLeave();
      if (this.movingPageNum != 0) return;
      this.isDown = false;
      let dtx = e.changedTouches[0].pageX - this.mousePos.X;
      let j = dtx < 0 ? -1 : 1;
      for (var i = this.pageNum; i >= 0; i--) {
        if (j * dtx > (i - 1) * this.pageWidth + 50) {
          this.movingPageNum = -j * i;
          if (this.translateX == (this.pageNum - j * i) * -this.pageWidth) {
            this.tranend();
          } else {
            this.translateX = (this.pageNum - j * i) * -this.pageWidth;
            if (this.movingPageNum == 0) this.tranend();
          }
          break;
        }
      }
    },
    change(index) {
      this.movingPageNum = index - this.curIdx;
      this.translateX =
        -this.pageWidth * this.pageNum + this.movingPageNum * -this.pageWidth;
      if (this.movingPageNum == 0) this.tranend();
    },
    tranend() {
      this.curIdx = this.formatIdx(this.curIdx + this.movingPageNum);
      this.movingPageNum = 0;
      this.translateX = -this.pageWidth * this.pageNum;
      !this.isEnter && this.restartAni();
    },
    formatIdx(idx) {
      var len = this.imglist.length;
      return idx % len < 0 ? len + (idx % len) : idx % len;
    },
    restartAni() {
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.change(this.curIdx + 1);
      }, 1500);
    },
  },
};
</script>

<style lang="less" scoped>
.banner {
  position: relative;
  width: 100%;
  overflow: hidden;
  margin-bottom: 30px;
  border-radius: 1.867vw;
  user-select: none;
  .content {
    display: flex;
    user-select: none;
    width: 100%;
    li {
      flex-shrink: 0;
      width: 100%;
      list-style: none;
      img {
        width: 100%;
        vertical-align: bottom;
        user-select: none;
      }
    }
  }
  .mark {
    position: absolute;
    z-index: 10;
    bottom: 1vw;
    width: 100%;
    margin: 0 auto;
    text-align: center;
    font-size: 0;
    span {
      display: inline-block;
      height: 1vw;
      width: 5vw;
      margin: 0 1vw;
      padding: 1vw 0;
      background-color: #b2b2b2;
      background-clip: content-box;
      transition: all 0.5s;
      cursor: pointer;
      opacity: 0.8;
      &.active {
        opacity: 1;
        background-color: #fff;
        width: 7vw;
      }
    }
  }
  .button1,
  .button2 {
    display: block;
    width: 6vw;
    height: 6vw;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: url(../assets/play.png) rgba(255, 255, 255, 0.3);
    background-size: contain;
    border-radius: 50%;
    cursor: pointer;
  }
  .button1 {
    left: 2vw;
    transform: translateY(-50%) scaleX(-1);
  }
  .button2 {
    right: 2vw;
  }
}
</style>